Software implementation errors, such as missing or incorrect input validation, can lead to out-of-bounds buffer accesses and memory corruption. These implementation errors can lead to the software becoming unstable or eventually crashing under normal conditions. However, when an input is manipulated by a malicious party intent on attacking the computer system, these memory corruption and overflow bugs can be exploited by the attacker to change the expected behavior of the software code and to execute code or functionality determined by the attacker.
An attacker typically gains control of execution by overwriting a data structure in memory, such as a return address, a function pointer, or a virtual-table pointer. Finding and fixing all exploitable memory-corruption bugs in large and legacy code-bases is not always possible. Accordingly, many computer systems contain general defensive features, called “exploit mitigation mechanisms,” that are effective against well-known techniques attackers use to exploit these bugs to gain control of and/or damage targeted computer systems.
Some examples of exploit mitigation mechanisms that are commonly included in computer systems include: Data Execution Prevention (DEP), Stack Protection (SP), and Address Space Layout Randomization (ASLR). In the DEP technique, all code sections are marked as read-only and all writable regions are non-executable. Typically, the read-only property of the code sections and the non-executable property of the writeable sections is enforced by the memory management unit (MMU) of the processor. This technique can prevent an attacker from placing their own code into a data area and directing execution flow to that code. In the SP approach, the compiler implements functions to detect buffer overflows on the stack. Stack-based buffer overflows can be easy to exploit, since there is often a return address or saved link-register on the stack right after a local array. An attacker can cause the local array to overflow and to overwrite the return address/link register and redirect execution flow of the software. Many conventional stack protection implementations insert a guard value onto the stack in the function prologue and check for modifications of that value before returning from that function. If a buffer overflow has occurred, the guard value will have been overwritten along with the return address, because the guard value is located in the stack between the buffer and the return address. The guard value must be a random and/or unpredictable value in order for the SP approach to be secure. In the ASLR approach, the memory layout of an application can be randomized at each execution. For example, the base address for code, static data, stack, and heap can be determined randomly. This approach makes exploitation difficult since attackers need to predict the location of the code/data/pointers they need to target/manipulate for a successful attack.